/*
	jGrouse framework
	Copyright 2007 by Denis Riabtchik 
	All rights reserved.
	
	Licensed under modified BSD license. See license.txt for details
*/

/**
	Contains classes encapsulating browser-specific functionality
	@module jgrouse.browser.HistoryTracker
*/

jgrouse.module(
{
	name : 'jgrouse.browser.HistoryTracker',
	requires : ['jgrouse.util.TaskManager'],
	body : function(embed)
	{
		eval(embed);
		
		/**
		 * Base class for history trackers
		 * @class jgrouse.browser.HistoryTracker
		 * @extends jgrouse.BaseObject
		 */
		jgrouse.define('jgrouse.browser.HistoryTracker', 'jgrouse.BaseObject', function(embed)
		{
			eval(embed);
			
			return {
				/**
				 * @constructor initialize
				 * @inheritdesc
				 */
				initialize : function()
				{
					this._currentHash = this._getHash();
				},
				
				setCurrentHash : function(value)
				{
					this._currentHash = value;
				},
				
				_getHash : function()
				{
					var v = window.location.hash;
					if (v)
					{
						v = v.substring(1);
					}				
					return unescape(v);
				},
				
				getNewEntry : function(entry)
				{
					var current = this._currentHash;
					if (entry)
					{
						if (entry.charAt(0) == '#')
						{
							if (!current)
							{
								current = '';
							}
							current = current.split('#')[0] + entry;
						}
						else
						{
							current = entry;
						}					
					}
					return current;
				},
				
				
				/**
				 * Set history entry 
				 * @function setHistoryEntry
				 * @param {String} value - value to be set 
				 */
				setHistoryEntry : function(value)
				{
					jgrouse.notImplemented(this.RTTI + '.setHistoryEntry');
				}, 
				
				/**
				 * Send notification when user navigates in history
				 */
				fireHistoryChange : function()
				{
					jgrouse.util.TaskManager.postPropertyChange('browserHistory', this._currentHash);
				}
			}
		});
		
		/**
		 * History tracker based on periodic polling of window.location.href
		 * @class jgrouse.browser.TimerHistoryTracker
		 * @extends jgrouse.browser.HistoryTracker
		 */
		jgrouse.define('jgrouse.browser.TimerHistoryTracker', 'jgrouse.browser.HistoryTracker', function(embed)
		{
			eval(embed);
			
			return {
				/**
				 * @constructor initialize
				 * @inheritdesc
				 */
				initialize : function(timeout)
				{
					_super(this, 'initialize');
					this._timer = window.setInterval(jgrouse.bind(this, this._onTimer), timeout);
				},
				
				/**
				 * @function setHistoryEntry
				 * @inheritdesc
				 */
				setHistoryEntry : function(entry)
				{
					var current = this.getNewEntry(entry);
					this.setCurrentHash(current);
					window.location.hash = '#' + escape(current);
					this.fireHistoryChange();
				},
				
				
				_onTimer : function()
				{
					var current = this._getHash();
					if (current != this._currentHash)
					{
						var old = this._currentHash;
						this._currentHash = current;
						this.fireHistoryChange();
					}
				}
			}
		});		
		
		/**
		 * History tracker based on detection of reloads of special document in hidden IFRAME
		 * @class jgrouse.browser.IFrameHistoryTracker
		 * @extends jgrouse.browser.HistoryTracker
		 */
		jgrouse.define('jgrouse.browser.IFrameHistoryTracker', 'jgrouse.browser.HistoryTracker', function(embed)
		{
			eval(embed);
			
			return {
				/**
				 * @constructor initialize
				 * @param {boolean} dontSetHash - indicates if the framework should not set 
				 * window.location.hash whenever user changes the browser history. Optional, default value is false.
				 */
				initialize : function(dontSetHash)
				{
					_super(this, 'initialize');
					this._historyFile = jgrouse.ClassLoader.instance.getResourcePath('jgrouse.browser.HistoryTracker', 'history.html');
					this._dontSetHash = dontSetHash;
					this._iframeRef = null;
				},
				
				historyChanged : function(entry)
				{
					this._currentHash = entry;
					if (!this._dontSetHash)
					{
						window.location.hash = '#' + entry;
					}					
					this.fireHistoryChange();
				},
				
				/**
				 * @function setHistoryEntry
				 * @inheritdesc
				 */
				setHistoryEntry : function(entry)
				{
					if (!this._iframeRef)
					{
						this._iframeRef = document.getElementById('_jgrouse_history_tracker');
					}
					var v = escape(this.getNewEntry(entry));
					
					if (!this._dontSetHash)
					{
						window.location.hash = '#' + v;
					}
					this.setCurrentHash(v);
					//note : bug in Opera - sometimes setting iframe.src does not result in change of iframe.contentWindow.location
					//bold assumption - both docs must be in the same domain
					//also, for Opera & Safari, sometimes contentWindow might be not initialized yet, will retry after delay
					if (this._iframeRef.contentWindow)
					{
						this._iframeRef.contentWindow.location.href = this._historyFile + '?' + v;
					}
					else
					{
						var athis = this;
						window.setTimeout(function(){athis._iframeRef.contentWindow.location.href = athis._historyFile + '?' + v;}, 200)
					}					
				}
				
			}
		});
	}
});

	